#include "dsp310.h"
#include "iic1.h"
#include <math.h>

#define DSP310_I2C_ADDR					(0x76)
#define DSP310_DEFAULT_CHIP_ID			(0x10)

#define DSP310_PRESSURE_MSB_REG			(0x00)  /* Pressure MSB Register */
#define DSP310_PRESSURE_LSB_REG			(0x01)  /* Pressure LSB Register */
#define DSP310_PRESSURE_XLSB_REG		(0x02)  /* Pressure XLSB Register */
#define DSP310_TEMPERATURE_MSB_REG		(0x03)  /* Temperature MSB Reg */
#define DSP310_TEMPERATURE_LSB_REG		(0x04)  /* Temperature LSB Reg */
#define DSP310_TEMPERATURE_XLSB_REG		(0x05)  /* Temperature XLSB Reg */
#define DSP310_PRESSURE_CFG_REG			(0x06)	/* Pressure configuration Reg */
#define DSP310_TEMPERATURE_CFG_REG		(0x07)	/* Temperature configuration Reg */
#define DSP310_MODE_CFG_REG				(0x08)  /* Mode and Status Configuration */
#define DSP310_INT_FIFO_CFG_REG			(0x09)	/* Interrupt and FIFO Configuration */
#define DSP310_INT_STATUS_REG			(0x0A)	/* Interrupt Status Reg */
#define DSP310_FIFO_STATUS_REG			(0x0B)	/* FIFO Status Reg */
#define DSP310_RST_REG					(0x0C)  /* Softreset Register */
#define DSP310_CHIP_ID					(0x0D)  /* Chip ID Register */
#define DSP310_COEFFICIENT_CALIB_REG	(0x10)  /* Coeffcient calibraion Register */

#define DSP310_CALIB_COEFFICIENT_LENGTH	(18)
#define DSP310_DATA_FRAME_SIZE			(6)

#define DSP310_CONTINUOUS_MODE			(0x07)

#define TEMPERATURE_INTERNAL_SENSOR		(0)
#define TEMPERATURE_EXTERNAL_SENSOR		(1)

//测量次数 times / S
#define DSP310_MWASURE_1					(0x00)
#define DSP310_MWASURE_2					(0x01)
#define DSP310_MWASURE_4					(0x02)
#define DSP310_MWASURE_8					(0x03)
#define DSP310_MWASURE_16				(0x04)
#define DSP310_MWASURE_32				(0x05)
#define DSP310_MWASURE_64				(0x06)
#define DSP310_MWASURE_128				(0x07)

//过采样率
#define DSP310_OVERSAMP_1				(0x00)
#define DSP310_OVERSAMP_2				(0x01)
#define DSP310_OVERSAMP_4				(0x02)
#define DSP310_OVERSAMP_8				(0x03)
#define DSP310_OVERSAMP_16				(0x04)
#define DSP310_OVERSAMP_32				(0x05)
#define DSP310_OVERSAMP_64				(0x06)
#define DSP310_OVERSAMP_128				(0x07)

#define P_MEASURE_RATE 			DSP310_MWASURE_16 	//每秒测量次数
#define P_OVERSAMP_RATE 		DSP310_OVERSAMP_64	//过采样率
#define DSP310_PRESSURE_CFG		(P_MEASURE_RATE<<4 | P_OVERSAMP_RATE)

#define T_MEASURE_RATE 			DSP310_MWASURE_16 	//每秒测量次数
#define T_OVERSAMP_RATE 		DSP310_OVERSAMP_8	//过采样率
#define DSP310_TEMPERATURE_CFG	(TEMPERATURE_EXTERNAL_SENSOR<<7 | T_MEASURE_RATE<<4 | T_OVERSAMP_RATE)

#define DSP310_MODE				(DSP310_CONTINUOUS_MODE)

const uint32_t scaleFactor[8] = {524288, 1572864, 3670016, 7864320, 253952, 516096, 1040384, 2088960};

typedef enum 
{
	PRESURE_SENSOR, 
	TEMPERATURE_SENSOR
}dsp310Sensor_e;

typedef struct dsp310CalibCoefficient_s
{
    int16_t c0;
    int16_t c1;
    int32_t c00;
    int32_t c10;
    int16_t c01;
    int16_t c11;
    int16_t c20;
    int16_t c21;
    int16_t c30;
}dsp310CalibCoefficient_t;

dsp310CalibCoefficient_t  dsp310Calib;

int32_t kp = 0;
int32_t kt = 0;
int32_t DSP310RawPressure = 0;
int32_t DSP310RawTemperature = 0;

static float alt = 0;
static void dsp310GetCalibParam(void)
{
	uint8_t buffer[DSP310_CALIB_COEFFICIENT_LENGTH] = {0};
	
	i2c1Read(DSP310_I2C_ADDR, DSP310_COEFFICIENT_CALIB_REG, buffer, DSP310_CALIB_COEFFICIENT_LENGTH);
	
	dsp310Calib.c0 = (int16_t)buffer[0]<<4 | buffer[1]>>4;
	dsp310Calib.c0 = (dsp310Calib.c0 & 0x0800) ? (dsp310Calib.c0 | 0xF000) : dsp310Calib.c0;
	
	dsp310Calib.c1 = (int16_t)(buffer[1] & 0x0F)<<8 | buffer[2];
	dsp310Calib.c1 = (dsp310Calib.c1 & 0x0800) ? (dsp310Calib.c1 | 0xF000) : dsp310Calib.c1;
	
	dsp310Calib.c00 = (int32_t)buffer[3]<<12 | (int32_t)buffer[4]<<4 | (int32_t)buffer[5]>>4;
	dsp310Calib.c00 = (dsp310Calib.c00 & 0x080000) ? (dsp310Calib.c00 | 0xFFF00000) : dsp310Calib.c00;
	
	dsp310Calib.c10 = (int32_t)(buffer[5] & 0x0F)<<16 | (int32_t)buffer[6]<<8 | (int32_t)buffer[7];
	dsp310Calib.c10 = (dsp310Calib.c10 & 0x080000) ? (dsp310Calib.c10 | 0xFFF00000) : dsp310Calib.c10;
	
	dsp310Calib.c01 = (int16_t)buffer[8]<<8 | buffer[9];
	dsp310Calib.c11 = (int16_t)buffer[10]<<8 | buffer[11];
	dsp310Calib.c20 = (int16_t)buffer[12]<<8 | buffer[13];
	dsp310Calib.c21 = (int16_t)buffer[14]<<8 | buffer[15];
	dsp310Calib.c30 = (int16_t)buffer[16]<<8 | buffer[17];
}

static void dsp310Rateset(dsp310Sensor_e sensor, uint8_t measureRate, uint8_t oversamplRate)
{
	uint8_t reg;
	if (sensor == PRESURE_SENSOR)
	{
		kp = scaleFactor[oversamplRate];
        uint8_t rate = measureRate<<4 | oversamplRate;
		i2c1Write(DSP310_I2C_ADDR, DSP310_PRESSURE_CFG_REG, &rate, 1);
		if (oversamplRate > DSP310_OVERSAMP_8)
		{
			i2c1Read(DSP310_I2C_ADDR, DSP310_INT_FIFO_CFG_REG, &reg, 1);
            reg |= 0x04;
			i2c1Write(DSP310_I2C_ADDR, DSP310_INT_FIFO_CFG_REG, &reg, 1);
		}
	}
	else if (sensor == TEMPERATURE_SENSOR)
	{
		kt = scaleFactor[oversamplRate];
        uint8_t rate = measureRate<<4 | oversamplRate | 0x80;
		i2c1Write(DSP310_I2C_ADDR, DSP310_TEMPERATURE_CFG_REG, &rate, 1);//Using mems temperature
		if (oversamplRate > DSP310_OVERSAMP_8)
		{
			i2c1Read(DSP310_I2C_ADDR, DSP310_INT_FIFO_CFG_REG, &reg, 1);
            reg |= 0x08;
			i2c1Write(DSP310_I2C_ADDR, DSP310_INT_FIFO_CFG_REG, &reg, 1);
		}
	}
}

// 判断芯片是否存在
static uint8_t existenceFlag = 0;


uint8_t dsp310Init(void)
{
	uint8_t id = 0;
	i2c1Read(DSP310_I2C_ADDR,DSP310_CHIP_ID, &id, 1);

	if (id == DSP310_DEFAULT_CHIP_ID)
	{
		existenceFlag = 1;

        // 延时40ms启动
        Ddl_Delay1ms(40);

        // 现在读取校准系数，温度系数源
        dsp310GetCalibParam();

        // 现在应用ADC温度增益设置
        // 首先在写0x0e和0x0f上来解锁地址0x62
        uint8_t regByte = 0xa5;
        i2c1Write(DSP310_I2C_ADDR,0x0e,&regByte,1);
        regByte = 0x96;
        i2c1Write(DSP310_I2C_ADDR,0x0f,&regByte,1);
        //然后更新温度的高增益值
        regByte = 0x02;
        i2c1Write(DSP310_I2C_ADDR,0x62,&regByte,1);
        //最后上锁位置0x62
        regByte = 0x00;
        i2c1Write(DSP310_I2C_ADDR,0x0e,&regByte,1);
        i2c1Write(DSP310_I2C_ADDR,0x0f,&regByte,1);
        // 配置压强和稳定
        dsp310Rateset(PRESURE_SENSOR, DSP310_MWASURE_16, DSP310_OVERSAMP_64);
	    dsp310Rateset(TEMPERATURE_SENSOR, DSP310_MWASURE_16, DSP310_OVERSAMP_64);
        // 启动
        regByte = DSP310_MODE;
		i2c1Write(DSP310_I2C_ADDR, DSP310_MODE_CFG_REG, &regByte,1);
	}
    return existenceFlag;
}

// 定义是否使用温度值来校正高度，1-使用，0-不使用
#define USE_TEMP 0

float getDsp310Data(void)
{
    if (existenceFlag)
	{
        uint8_t buffer[DSP310_DATA_FRAME_SIZE] = {0};

        i2c1Read(DSP310_I2C_ADDR, DSP310_PRESSURE_MSB_REG, buffer, DSP310_DATA_FRAME_SIZE);
        int32_t rawPressure = (int32_t)buffer[0]<<16 | (int32_t)buffer[1]<<8 | (int32_t)buffer[2];
		rawPressure = (rawPressure & 0x800000) ? (0xFF000000 | rawPressure) : rawPressure;
		
		int32_t rawTemp = (int32_t)buffer[3]<<16 | (int32_t)buffer[4]<<8 | (int32_t)buffer[5];
		rawTemp = (rawTemp & 0x800000) ? (0xFF000000 | rawTemp) : rawTemp;
		
        // 温度
        float fTsc;
        fTsc = rawTemp / (float)kt; 

        // 压强
        float fPsc;
        float qua2, qua3;
        float fPCompensate;
        fPsc = rawPressure / (float)kp;
        qua2 = dsp310Calib.c10 + fPsc * (dsp310Calib.c20 + fPsc* dsp310Calib.c30);
        qua3 = fTsc * fPsc * (dsp310Calib.c11 + fPsc * dsp310Calib.c21);
        fPCompensate = dsp310Calib.c00 + fPsc * qua2 + fTsc * dsp310Calib.c01 + qua3;

        float pressure = fPCompensate * 0.001f;//kpa

        // 只根据压强计算
        alt = 44330.0f * (1 - powf((pressure / 101.325f), 0.190295f));
#if (USE_TEMP)	
        float fTCompensate;
        fTCompensate =  dsp310Calib.c0 * 0.5 + dsp310Calib.c1 * fTsc;
        // 根据压强和温度同时计算
        alt = 153.84615f * ((powf((101.325f/pressure), 0.190295f) - 1) * (fTCompensate+273.15f));
#endif
    }
    return alt;
}

